﻿// <copyright file="IModCollection.cs" company="SingularityShift">
// Copyright (c) 2009 SingularityShift.com
// </copyright>
// <author>Ben McClure</author>
// <email>ben@singularityshift.com</email>
// <date>2009-08-14</date>
// <summary>A public interface which defines an object representing a collection of game mods</summary>
namespace GameLib.Games
{
    using System;
    using System.Collections.Generic;
    using System.Xml.Serialization;
    using GameLib.Games.Util;

    /// <summary>
    /// A non-generic base interface for a collection of IMods. The collection itself is not defined here, just base methods!
    /// </summary>
    public interface IModCollection : ICloneable
    {
        /// <summary>
        /// Thrown whenever the ModList has been imported into.
        /// </summary>
        event EventHandler<EventArgs> ModListImported;

        /// <summary>
        /// Thrown whenever the ModList has been exported from.
        /// </summary>
        event EventHandler<EventArgs> ModListExported;

        /// <summary>
        /// Gets or sets the SortType enum that defines how this list should be sorted.
        /// </summary>
        ModSortTypes SortBy
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the DateTime object indicating when this list was created.
        /// </summary>
        DateTime Created
        {
            get;
            set;
        }

        /// <summary>
        /// Exports the Ids of the IMod objects in the list to a text file.
        /// </summary>
        /// <param name="textFile">The file to output the list objects to.</param>
        /// <returns>An int specifying the number of objects exported</returns>
        int Export(string textFile);

        /// <summary>
        /// Exports the Ids of the IMod objects in the list to a text file.
        /// </summary>
        /// <param name="textFile">The file to output the list objects to.</param>
        /// <param name="overwrite">Whether or not to overwrite the text file if it exists.</param>
        /// <returns>An int specifying the number of objects exported</returns>
        int Export(string textFile, bool overwrite);

        /// <summary>
        /// Indicates whether any mod in the list conflicts with any other mod in the list.
        /// </summary>
        /// <returns>A boolean indicating whether the list has any conflicts.</returns>
        bool HasMatchingConflicts();

        /// <summary>
        /// Indicates whether any mod in the list is has any dependency found in the list.
        /// </summary>
        /// <returns>A boolean indicating if there are matching dependencies in the list.</returns>
        bool HasMatchingDependencies();

        /// <summary>
        /// Indicates whether any mod in the list is has any dependency not found in the list.
        /// </summary>
        /// <returns>A boolean indicating if there are missing dependencies in the list.</returns>
        bool HasMissingDependencies();

        /// <summary>
        /// Indicates whether any mod in the list has messages matching any other mod in the list.
        /// </summary>
        /// <returns>A boolean indicating if there are matching messages in the list.</returns>
        bool HasMatchingMessages();

        /// <summary>
        /// Imports IMod objects from files in a specified directory.
        /// </summary>
        /// <param name="dir">The directory to import files from.</param>
        /// <param name="searchPattern">The search pattern to find mods based on.</param>
        /// <param name="sortBy">The SortType enum describing how to sort the imported IMods.</param>
        /// <returns>An integer indicating the number of mods imported.</returns>
        int Import(string dir, string searchPattern, ModSortTypes sortBy);

        /// <summary>
        /// Imports IMod objects from a text file containing a list of Ids.
        /// </summary>
        /// <param name="textFile">The text file to import. This should contain a delimited list of mod Ids.</param>
        /// <returns>An integer indicating the number of mods imported.</returns>
        int Import(string textFile);

        /// <summary>
        /// Imports IMod objects from a text file containing a list of Ids.
        /// </summary>
        /// <param name="textFile">The text file to import. This should contain a delimited list of mod Ids.</param>
        /// <param name="sortBy">A SortType enum describing how to sort the imported mods in the list.</param>
        /// <returns>An integer indicating the number of mods imported.</returns>
        int Import(string textFile, ModSortTypes sortBy);

        /// <summary>
        /// Imports IMod objects from a text file of Filenames, supplementing the other information based on real files in the provided directory.
        /// </summary>
        /// <param name="textFile">The file containing a delimited list of mod filenames to import.</param>
        /// <param name="sortBy">A SortType enum indicating how to sort the imported IMod objects.</param>
        /// <param name="dir">The system directory containing mod files to get other information about each mod from.</param>
        /// <returns>An integer indicating the number of mods imported.</returns>
        int Import(string textFile, ModSortTypes sortBy, string dir);

        /// <summary>
        /// Sorts mods using the specified SortType enumeration value
        /// </summary>
        /// <param name="sortBy">A SortType enumeration indicating how to sort the mods.</param>
        void SortMods(ModSortTypes sortBy);

        /// <summary>
        /// Sorts mods using the specified SortType enumeration and the mod information in the provided system directory.
        /// </summary>
        /// <param name="sortBy">A SortType enumeration indicating how to sort the mods.</param>
        /// <param name="dir">A filesystem directory containing the mods to sort by</param>
        void SortMods(ModSortTypes sortBy, string dir);
    }

    /// <summary>
    /// An interface which represents an ordered and manageable list of IMods for a particular game.
    /// </summary>
    /// <typeparam name="T">The type of IMod this collection contains</typeparam>
    public interface IModCollection<T> : IModCollection, IList<T> where T : IMod
    {
        /// <summary>
        /// Gets the game which owns (is the parent of) this list. The game should also own all mods within the list.
        /// </summary>
        IGame<T> Owner
        {
            get;
        }

        /// <summary>
        /// Gets an Array of IMod objects in this list.
        /// </summary>
        [XmlArray()]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "This is used for serialization/deserialiation, since it can't serialize the list properly.")]
        T[] ModArray
        {
            get;
        }

        /// <summary>
        /// Gets or sets the IMod specified by the provided Id string. This requires no casting.
        /// </summary>
        /// <param name="id">The Id of the mod to get</param>
        T this[string id]
        {
            get;
            set;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Sets an owner. </summary>
        ///
        /// <param name="game"> The game. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        void SetOwner(IGame game);

        /// <summary>
        /// Finds all IMod objects in the list where the specified field matches the provided value.
        /// </summary>
        /// <param name="field">The field within each IMod object to search in</param>
        /// <param name="value">The value to match against the field</param>
        /// <returns>An IList of IMod objects that match the specified query</returns>
        IModCollection<T> Find(string field, object value);

        /// <summary>
        /// Finds all IMod objects in the list where the specified field matches the provided value, optionally supporting regular expressions.
        /// </summary>
        /// <param name="field">The field within each IMod object to search in</param>
        /// <param name="value">The value to match against the field</param>
        /// <param name="regex">A bool indicating whether the search value is a RegEx pattern or not</param>
        /// <returns>An IList of IMod objects that match the specified query</returns>
        IModCollection<T> Find(string field, object value, bool regex);

        /// <summary>
        /// <para>Clears the list and uses the IMod objects in the provided array to repopulate it.</para>
        /// <para>This will clear any previous IMods from the list.</para>
        /// </summary>
        /// <param name="mods">The array of IMod objects to turn the list into.</param>
        void FromArray(T[] mods);

        /// <summary>
        /// Inserts the provided IMod object after the other provided IMod object.
        /// </summary>
        /// <param name="thisMod">THe IMod object to insert.</param>
        /// <param name="otherMod">The IMod object to insert the mod after</param>
        /// <returns>The index the mod was inserted at.</returns>
        int InsertAfter(T thisMod, T otherMod);

        /// <summary>
        /// Inserts the provided IMod object before the other provided IMod object.
        /// </summary>
        /// <param name="thisMod">The IMod object to insert.</param>
        /// <param name="otherMod">The IMod object to insert the mod before.</param>
        /// <returns>The index the mod was inserted at.</returns>
        int InsertBefore(T thisMod, T otherMod);

        /// <summary>
        /// <para>Determines whether this list contains a mod like the IMod object specified.</para>
        /// <para>This matches true if the Id matches, usually.</para>
        /// </summary>
        /// <param name="thisMod">The IMod object to check for.</param>
        /// <returns>A value indicating whether the mod described by thisMod is contained within this collection</returns>
        bool ContainsMod(T thisMod);

        /// <summary>
        /// Determines whether this list contains a mod having the specified Id
        /// </summary>
        /// <param name="id">The Id string to check for in the list</param>
        /// <returns>A value indicating whether the mod described by this id is contained within this collection</returns>
        bool ContainsMod(string id);

        bool ContainsPattern(string pattern);

        /// <summary>
        /// Removes a mod from this collection
        /// </summary>
        /// <param name="thisMod">The mod to remove from the collection</param>
        void RemoveMod(T thisMod);

        /// <summary>
        /// Returns a new array of IMod objects from the IMods in the list.
        /// </summary>
        /// <returns>The new array</returns>
        T[] ToArray();
    }
}